#ifndef _SERVICE_H_
#define _SERVICE_H_

#include <event.h>
#include <assert.h>

#include "thread.h"
#include "conn.h"
#include "timing.h"

#define SRV_PID_PATH		"/tmp/srv.pid"
#define SRV_PATH_SIZE		64

#define WORKERS_NUM_MAX		16
#define IFACES_NUM_MAX		16
#define TIMINGS_NUM_MAX		16
#define INTERVAL_USEC_MAX	(60*60*24*365)		//one year

//socket type
enum SOCKET_TYPE {
	TYPE_SERVER = 1, 
	TYPE_CLIENT = 2,
};

enum SERVICE_STAT {
	SRV_READY = 0,
	SRV_RUNNING = 1,
	SRV_SHUTTING = 2,
	/* others */
};

/* init args */
typedef struct IFACE_ARG {
	enum SOCKET_TYPE	type;
	int					port;
	char				addr[IPADDR_SIZE];
	DEPACK_FUNC			depack;
	ONPACK_FUNC			onpack;
} IFACE_ARG;

typedef struct THREAD_ARG {
	TH_ONTASK_FUNC		ontask;
	TH_INIT_FUNC		init;
	TH_CLEAR_FUNC		clear;
} THREAD_ARG;

typedef struct TIMING_ARG {
	unsigned int		usec;
	ONTIMING_FUNC		ontiming;
} TIMING_ARG;

typedef struct SERVICE {
/* private */
	enum SERVICE_STAT	stat;					/* service stat or error code */
	int			pid;							/* pid saved to pid file */
	char		pidpath[SRV_PATH_SIZE];			/* pid file */
	int			pidfd;

	IFACE_ARG	ifaces_arg[IFACES_NUM_MAX];		/* set ifaces */

	THREAD_ARG	master_arg;						/* set master */
	THREAD_ARG	timer_arg;						/* set timer */
	THREAD_ARG	workers_arg[WORKERS_NUM_MAX];	/* set workers */

	TIMING_ARG	timings_arg[TIMINGS_NUM_MAX];	/* set timings */

	TIMING		*timings[TIMINGS_NUM_MAX];		/* set to timer->sys */
	LOGGING		*loggings[LV_NUMS];				/* set to logger->sys */
	int			level;

/* public */
	int			ifaces_num;
	CONN		*ifaces[IFACES_NUM_MAX];		/* ifaces conn */
	int			timings_num;
	int			workers_num;
	int			next_workeri;
	THREAD		*workers[WORKERS_NUM_MAX];		/* workers thread */
	THREAD		*logger;						/* logger thread */
	THREAD		*master;						/* master thread */
	THREAD		*timer;							/* timer thread */
} SERVICE;

/* log task data */
typedef struct TASK_LOG {
	int	level;
	char * buf;
} TASK_LOG;

void service_run();

int service_dispatch_workeri(TASK * task, unsigned int workeri);
int service_dispatch_rang(TASK * task, unsigned int from_workeri, unsigned int to_workeri);
int service_dispatch(TASK * task);

void service_set_log_level(unsigned int level);

void service_set_log(const char * path, unsigned int level, unsigned int bufsz);

void service_set_master(TH_ONTASK_FUNC ontask, TH_INIT_FUNC init, TH_CLEAR_FUNC clear);

void service_set_timer(TH_ONTASK_FUNC ontask, TH_INIT_FUNC init, TH_CLEAR_FUNC clear);

void service_add_workers(unsigned int workers_num, 
		TH_ONTASK_FUNC ontask, TH_INIT_FUNC init, TH_CLEAR_FUNC clear);

void service_add_iface(enum SOCKET_TYPE type, const char * ip, unsigned int port, 
						DEPACK_FUNC depack, ONPACK_FUNC onpack);

void service_add_timing(unsigned int usec, ONTIMING_FUNC ontiming, 
						TH_ONTASK_FUNC ontask, TH_INIT_FUNC init, TH_CLEAR_FUNC clear);

void service_set_pid_path(const char * path);

#endif
